import java.util.ArrayList;
import java.util.List;

import com.google.caliper.BeforeExperiment;
import com.google.caliper.api.Macrobenchmark;

public class SudokuAlgorithmBench {
    int numOfTests = 4;
    List<List<List<List<Integer>>>> puzzles;
    BacktrackingSolver bt;
    SATContraintSolver sat;
    DancingLinksSolver dlx;
    StrategyBasedSolver sbs;
    boolean dummy;

    @BeforeExperiment
    void setUp() throws Exception {
        bt = new BacktrackingSolver();
        sat = new SATContraintSolver();
        dlx = new DancingLinksSolver();
        sbs = new StrategyBasedSolver();
        puzzles = new ArrayList<List<List<List<Integer>>>>(numOfTests);
        // build puzzles for each bench
        for (int i = 0; i < numOfTests; i++) {
            PuzzleLoader pl = new PuzzleLoader("1_0-1_3puzzles.txt");
            pl.parse();
            puzzles.add(pl.getParsedPuzzles());
        }
    }

    @Macrobenchmark
    boolean BacktrackingSolve(int reps) {

        for (int i = 0; i < reps; i++) {
            for (List<List<Integer>> puzzle : puzzles.get(0)) {
                List<List<Integer>> solution = bt.solve(puzzle);
                dummy = solution.isEmpty();
            }
        }
        return dummy;
    }

    @Macrobenchmark
    boolean SATSolve(int reps) {
        for (int i = 0; i < reps; i++) {
            for (List<List<Integer>> puzzle : puzzles.get(1)) {
                List<List<Integer>> solution = sat.solve(puzzle);
                dummy = solution.isEmpty();
            }
        }
        return dummy;
    }

    @Macrobenchmark
    boolean DLXSolve(int reps) {
        for (int i = 0; i < reps; i++) {
            for (List<List<Integer>> puzzle : puzzles.get(2)) {
                List<List<Integer>> solution = dlx.solve(puzzle);
                dummy = solution.isEmpty();
            }
        }
        return dummy;
    }

    @Macrobenchmark
    boolean SBSolve(int reps) {
        for (int i = 0; i < reps; i++) {
            for (List<List<Integer>> puzzle : puzzles.get(3)) {
                List<List<Integer>> solution = sbs.solve(puzzle);
                dummy = solution.isEmpty();
            }
        }
        return dummy;
    }
}
